#include "animatedwiget.h"

webWidget::webWidget(QWidget *parent)
//        QWebView(parent)
{
    setParent(parent);
    leftButTrigger = Qt::LeftButton;
    rightButTrigger = Qt::RightButton;
}

void webWidget::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == leftButTrigger) {
        emit leftButClicked();
    }
    else if (event->button() == rightButTrigger)
        emit rightButclicked();
    else
        return;
}

animatedWidget::animatedWidget(QWidget *parent) :
        QWidget(parent,Qt::ToolTip|Qt::FramelessWindowHint),fillType(animatedWidget::monoChrom),defaultSize(350,110)
{
    startState = new QState();
    hideState = new QState();
    showState = new QState();
    doneState = new QFinalState();

    message = new webWidget(this);
    message->setStyleSheet ("background: transparent");
    message->setContextMenuPolicy(Qt::NoContextMenu);
    message->page ()->mainFrame ()->setScrollBarPolicy ( Qt::Horizontal, Qt::ScrollBarAlwaysOff );
    message->page ()->mainFrame ()->setScrollBarPolicy ( Qt::Vertical, Qt::ScrollBarAlwaysOff );

    resize(defaultSize);
    message->resize(defaultSize);

    message->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::MinimumExpanding);
    message->page()->setPreferredContentsSize(defaultSize);

    qDebug() << "Widget created";
}

animatedWidget::~animatedWidget()
{
    delete hideState;
    delete showState;
}

int animatedWidget::setAnimation()
{
    qDebug() << "Set animation";

    move(topLeft);

    QRect geom = geometry();

    startState->assignProperty(this, "windowOpacity", 0.0);
    startState->assignProperty(this, "geometry", geom);

    hideState->assignProperty(this, "windowOpacity", 0.0);
    hideState->assignProperty(this, "geometry", geom);

    geom.moveLeft(geom.left()-geom.width());

    showState->assignProperty(this, "windowOpacity", 0.9);
    showState->assignProperty(this, "geometry", geom);

    qDebug() << "Create animations";

    opacityAnim = new QPropertyAnimation(this, "windowOpacity");
    opacityAnim->setEasingCurve(QEasingCurve::InOutCubic);
    opacityAnim->setDuration(1000);

    geometryAnim = new QPropertyAnimation(this, "geometry");
    geometryAnim->setEasingCurve(QEasingCurve::InOutCubic);
    geometryAnim->setDuration(600);

    qDebug() << "Create transitions";

    showTransition = new animationTransition(animationTransition::show);
    showTransition->setTargetState(showState);
    showTransition->addAnimation(opacityAnim);
    showTransition->addAnimation(geometryAnim);
    startState->addTransition(showTransition);

    hideTransition = new animationTransition(animationTransition::hide);
    hideTransition->setTargetState(hideState);
    hideTransition->addAnimation(opacityAnim);
    hideTransition->addAnimation(geometryAnim);
    showState->addTransition(hideTransition);

    updateTransition = new animationTransition(animationTransition::update);
    updateTransition->setTargetState(showState);
    updateTransition->addAnimation(geometryAnim);
    showState->addTransition(updateTransition);

    hideState->addTransition(hideState,SIGNAL(propertiesAssigned()),doneState);

    qDebug() << "Make connections";

    connect (&machine, SIGNAL(started()), this, SLOT(showMe()));
    connect (&machine, SIGNAL(finished()), this, SLOT(finish()));
    QTimer::singleShot(6000, this, SLOT(hideMe()));

    connect (&machine, SIGNAL(started()), this, SLOT(debugMachine()));
    connect (&machine, SIGNAL(stopped()), this, SLOT(debugMachine()));
    connect (&machine, SIGNAL(finished()), this, SLOT(debugMachine()));

    connect(message, SIGNAL(leftButClicked()), this, SLOT(activMe()));
    connect(message, SIGNAL(rightButclicked()), this, SLOT(hideMe()));

    qDebug() << "Add states";

    machine.addState(startState);
    machine.addState(showState);
    machine.addState(hideState);
    machine.addState(doneState);
    machine.setInitialState(startState);

    qDebug() << "Start machine";

    machine.start();

    return 0;
}

int animatedWidget::updateState()
{
    QRect geom = geometry();

    geom.moveTo(topLeft);

    hideState->assignProperty(this, "geometry", geom);

    geom.moveLeft(geom.left()-geom.width());

    showState->assignProperty(this, "geometry", geom);

    qDebug() << "update state";

    machine.postEvent( new animationTransition::animationEvent(animationTransition::update));

    return 0;
}

void animatedWidget::showMe()
{
    show();

    qDebug() << "Go to show state";

    machine.postEvent( new animationTransition::animationEvent(animationTransition::show));
}

void animatedWidget::hideMe()
{
    qDebug() << "Go to hide state";
    machine.postEvent( new animationTransition::animationEvent(animationTransition::hide));
}

void animatedWidget::activMe()
{
    qDebug() << "Notify activated";
    emit activated ();
    hideMe();
}

void animatedWidget::paintEvent(QPaintEvent *event)
{
    QRectF wgtRect(QPointF(1.0,1.0), this->size()-=QSize(2,2));

    QPainter painter(this);
    painter.save();
    painter.setRenderHint(QPainter::Antialiasing);
//    painter.setOpacity(0.55);

    QPainterPath roundRectPath;
    roundRectPath.addRoundedRect(wgtRect, 18.0, 18.0);
    painter.setClipPath(roundRectPath);
    QRegion maskregion = painter.clipRegion();
    setMask(maskregion);
    roundRectPath.setFillRule(Qt::WindingFill);
    switch (fillType)
    {
    case animatedWidget::monoChrom:
        {
            painter.fillRect(wgtRect, Qt::green);
            break;
        }
    case animatedWidget::lineGrad:
        {
            QLinearGradient gradient(0, 0, 0, wgtRect.height());
            gradient.setColorAt(0.0, QColor(250,250,250));
            gradient.setColorAt(1.0, QColor(100,100,100));
            painter.setBrush(gradient);
            break;
        }
    case animatedWidget::radialGrad:
        {
            QRadialGradient gradient(wgtRect.width()/2, wgtRect.height()/2, wgtRect.width(), wgtRect.width()/2, wgtRect.height()/2);
            gradient.setColorAt(0.0, QColor(250,250,250));
            gradient.setColorAt(1.0, QColor(100,100,100));
            painter.setBrush(gradient);
            break;
        }
    }

    painter.drawPath(roundRectPath);
    painter.restore();

//    qreal opacity(0.675);
//    int roundness(40);
//    QRect widget_rect = this->rect();

//    QPainter painter(this);
//    painter.save();

//    painter.setRenderHint(QPainter::Antialiasing);
//    painter.setPen(Qt::red);

//    // clip
//    QPainterPath rounded_rect;
//    rounded_rect.addRoundRect(1, 1, widget_rect.width() - 2, widget_rect.height() - 2, roundness, roundness);
//    painter.setClipPath(rounded_rect);

//    // get clipping region
//    QRegion maskregion = painter.clipRegion();

//    // mask the widget
//    setMask(maskregion);
//    painter.setOpacity(opacity);

//    // fill path with color
//    painter.fillPath(rounded_rect,QBrush(Qt::black));

//    // restore painter
//    painter.restore();
}

void animatedWidget::updateMe()
{
    resize (message->page()->mainFrame()->contentsSize());
    message->resize(message->page()->mainFrame()->contentsSize());

    qDebug() << "new size: " << message->page()->mainFrame()->contentsSize();

    emit updated();
}

int animatedWidget::setMessage(QString title, QString msg, QString imagePath)
{
    QString data;
    QFile content ("./res/tmp.html");
    if (content.open(QIODevice::ReadOnly))
    {
        data = content.readAll();
        data.replace ( "{title}", title );
        data.replace ( "{body}", msg );
        data.replace ( "{imagepath}", MakeImage (imagePath));
        content.close();
        connect (message, SIGNAL(loadFinished(bool)), this, SLOT(updateMe()));
        message->setHtml(data);
        resize (message->page()->mainFrame()->contentsSize());
        message->resize(message->page()->mainFrame()->contentsSize());

        qDebug() << "size: " << message->page()->mainFrame()->contentsSize();
    }
//    emit showWgt();
    return 0;
}

void animatedWidget::finish()
{
    delete opacityAnim;
    delete geometryAnim;
    delete showTransition;
    delete hideTransition;
    emit finished();
    qDebug() << "notify finished";
}

QByteArray animatedWidget::MakeImage (const QString& path)
{
        QBuffer iconBuffer;
        iconBuffer.open (QIODevice::ReadWrite);
        QPixmap pixmap (path);
        pixmap.save (&iconBuffer, "PNG");
        return QByteArray ("data:image/png;base64,") + iconBuffer.buffer ().toBase64 ();
}

void animatedWidget::testSlot()
{

}

void animatedWidget::debugMachine()
{
//    qDebug() << "machine running" << machine.isRunning();
//    qDebug() << "machine error" << machine.error();
}

void animationTransition::onTransition(QEvent *event)
{
    if (event->type() == QEvent::Type(QEvent::User+1))
    {
        animationEvent *se = static_cast<animationEvent*>(event);
        switch (se->value)
        {
            case show: qDebug() << "Make show transition";
                break;
            case hide: qDebug() << "Make hide transition";
                break;
            case update: qDebug() << "Make update transition";
        }
    }
    else
    {
        qDebug() << "Unknown transition";
    }
}

bool animationTransition::eventTest(QEvent *e)
{
    if (e->type() != QEvent::Type(QEvent::User+1))
        return false;
    animationEvent *se = static_cast<animationEvent*>(e);
    return (m_value == se->value);
}
